<template>
  <vp-dialog ref="editDialogRef" :span="2">
    <template #title>
        <vp-label zh="选择人员" en="Choose User" align="left"/>
    </template>
			<vp-card shadow="hover" class="mb5">
          <el-form label-suffix=":"  ref="searchFormRef" :model="searchForm" @submit.prevent
            @keyup.enter="handleSearch" label-width="120px">
            <vp-search-row >
              <vp-search-col :span="2">
                <el-form-item prop="keyword">
                  <template #label><vp-label-keyword/></template>
                  <el-input v-model="searchForm.keyword" v-trim placeholder=""></el-input>
                </el-form-item>
              </vp-search-col>
              <vp-search-col btn-col>
                <vp-btn-search :loading="loading" @click="handleSearch"/>
                <vp-btn-reset @click="handleSearchReset"/>
            </vp-search-col>
            </vp-search-row>
          </el-form>
			</vp-card>
      <el-row>
        <vp-col :span="2" class="pr5">
          <vp-card shadow="hover" v-loading="loading" class="department-tree">
            <span class="custom-tree-label">
							<span>按部门/By Department</span>
						</span>
            <el-scrollbar height="calc(100vh - 500px)">
              <el-tree 
                :key="nodeKey"
                node-key="treeId"
                show-checkbox
                ref="departmentTreeRef"
                :data="processDepartmentData" 
                :default-checked-keys="defaultCheckedKeys4Department"
                :props="defaultProps" 
                :default-expand-all="expandAll"
                :expand-on-click-node="false"
                :check-on-click-node="true"
                :filter-node-method="filterNode"
                @check="handleCheckChangeByDepartment">
                <template #default="{ node, data }">
                  <el-icon v-if="data.type === 1"><ele-OfficeBuilding /></el-icon>
                  <el-icon v-if="data.type === 2"><ele-Avatar /> </el-icon>
                  <span class="pl8">
                    <span v-html="markTextColor(searchForm.keyword, node.label)" />
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </vp-card>
        </vp-col>
        <vp-col :span="2" class="pl5">
          <el-card shadow="hover" v-loading="loading" class="post-tree">
            <span class="custom-tree-label">
							<span>按岗位/By Post</span>
						</span>
            <el-scrollbar height="calc(100vh - 500px)">
              <el-tree 
                :key="nodeKey"
                node-key="treeId"
                show-checkbox
                ref="positionTreeRef"
                :data="processPositionData" 
                :default-checked-keys="defaultCheckedKeys4Position"
                :props="defaultProps" 
                :default-expand-all="expandAll"
                :expand-on-click-node="false"
                :check-on-click-node="true"
                @check="handleCheckChangeByPosition">
                <template #default="{ node, data }">
                  <el-icon v-if="data.type === 1" class="fa fa-wpforms"></el-icon>
                  <el-icon v-if="data.type === 2"><elementAvatar /> </el-icon>
                  <span class="pl8">
                    <span v-html="markTextColor(searchForm.keyword, node.label)" />
                  </span>
                </template>
              </el-tree>
            </el-scrollbar>
          </el-card>
        </vp-col>
      </el-row>
      <el-row>
        <span class="custom-tree-label" style="min-height: 32px;padding-top: 5px;">已选人员/Checked Person：</span>
        <el-tag
          v-for="tag in checkedPerson"
          :key="tag.id"
          class="ml5 mr5"
          closable
          type="success"
          effect="dark"
          @close="handleCloseTag(tag)"
        >
          {{ tag.label }}
        </el-tag>
      </el-row>
		<template #footer>
      <vp-btn-confirm  @click="handleSave"/>
		</template>
  </vp-dialog>
</template>
<script lang="ts">
	import { computed, defineComponent, nextTick, reactive, ref, toRefs } from 'vue';
	import request from '/@/utils/request';
  import { markTextColor } from "/@/utils/toolsValidate";

  interface UserDialogParam {
    type: 1 | 2;  //1、选择人员t_user 2、选择档案b_p3_001
    multi: boolean; // 是否多选
    selected: string | string[];  // 默认选中人员id
    gwid?: string;  // 筛选岗位id
    bmid?: string;  // 筛选部门id
    gwidList?: []; // 筛选多个岗位id
    gwdmList?: []; // 筛选多个岗位代码（M/E/I/R/PPC）
    callback: (data:any)=>{}; // 回调方法
  }

  interface UserTreeNode {
    id: string;
    treeId: string;
    label: string;
    type: 1 | 2;
    bmdm?: string;
    children?: UserTreeNode[];
  }

	export default defineComponent({
		name: "userDialog",
		components: { },
		setup(props, context) {
			const state = reactive({
				searchForm: {
					keyword: "",
          gwid: "",
          bmid: "",
          gwidList: [],
          gwdmList: [],
				},
        isReload: true, //是否重新加载（每次打开弹窗后重新加载，后续查询不加载）
				users: [],  //当前用户（按搜索条件过滤后）
        allUsers: [], //所有用户
        departments: [],
        positions: [],
        type: 1,
        multi: false,
        defaultSelected: [] as String[],  // 默认选中人员
        currentSelected: [] as String[],  // 当前选中人员
        callback:(data: any)=>{},
        loading: false,
        defaultProps: {
          children: 'children',
          label: 'label',
          disabled: (data: UserTreeNode)=> {
            return !state.multi && data.type === 1;
          }
        },
        nodeKey:"key",
        expandAll:false,
			});
			const editDialogRef = ref();
			const searchFormRef = ref();
      const departmentTreeRef = ref();
      const positionTreeRef = ref();

			const handleOpen = (param: UserDialogParam) => {
				editDialogRef.value.handleOpen();
        state.type = param.type;
        state.multi = param.multi;
        state.searchForm.gwid = param.gwid || '';
        state.searchForm.bmid = param.bmid || '';
        state.searchForm.gwidList = param.gwidList || [];
        state.searchForm.gwdmList = param.gwdmList || [];
        if (param.callback && typeof param.callback === "function") {
          state.callback = param.callback;
        }
        if (!param.selected) {
          state.defaultSelected = [];
        } else if (typeof(param.selected) === 'string') {
          state.defaultSelected = [param.selected];
        } else {
          state.defaultSelected = param.selected;
        }
        state.currentSelected = [...state.defaultSelected];
        state.isReload = true;
				loadDataList();
         // 关键字搜索定位
         getKeyWordPostion();
			}

			const loadDataList = () => {
        if (state.isReload) {
          state.loading = true;
          request.get('/system/user/tree/list',{
            params: {
              type: state.type,
              gwid: state.searchForm.gwid,
              bmid: state.searchForm.bmid,
              gwidList: state.searchForm.gwidList,
              gwdmList: state.searchForm.gwdmList
            }
          }).then(res => {
            state.allUsers = res?.data?.users || [];
            state.allUsers.forEach((user: any) => {
              user.treeId = user.id;
              user.label = user.zh + ' ' + user.xm;
              user.type = 2;
            });
            state.departments = res?.data?.departments || [];
            state.positions = res?.data?.positions || [];
            state.expandAll = !!state.searchForm.keyword || !!state.searchForm.bmid;
            state.nodeKey = new Date().getTime() + "";
            state.isReload = false;
            // 多选时，将传入参数中默认选中值，由rydaid重置为为userid
            handleSelectedParam();
            setCurrentUsers();
          }).finally(() => {
            state.loading = false
          })
        } else {
          state.expandAll = !!state.searchForm.keyword || !!state.searchForm.bmid;
          state.nodeKey = new Date().getTime() + "";
          setCurrentUsers();
          state.defaultSelected = [...state.currentSelected];
        }
			}

			const handleSave = () => {
				if (state.loading) {
					return;
				}

        const checked = checkedPerson.value.map((user: any) => {
          return {
            yhid: user.yhid,
            xm: user.xm,
            zh: user.zh,
            daid: user.daid,
            bmdm: user.bmdm,
            dabh: user.dabh,
            bmmc: user.bmmc
          }
        });
        state.callback(state.multi ? checked : (checked.length > 0 ? checked[0] : {}));
				editDialogRef.value.handleClose();
			}

			const handleSearch = () => {
				loadDataList();
        // 关键字搜索定位
        getKeyWordPostion();
			}

      const getKeyWordPostion = () =>{
        nextTick(() => {
          if(!state.searchForm.keyword){
            return;
          }
          let id = '';
          state.users.forEach((user: any) => {
            if ((user.xm && user.xm.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) != -1) || (user.zh && user.zh.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) != -1)) {
               id = user.id;
               return;
            }
          });
          if(id){
            const node: any = document.querySelector('.department-tree .el-tree-node[data-key="'+id+'"]');
            node.scrollIntoView({ block: 'center' });
          }
          let postKey = '';
          (processPositionData.value || []).forEach((position: any) => {
          if(postKey){
            return;
           }
            if(position.children && position.children.length > 0){
              position.children.forEach((user:any) =>{
                if(postKey){
                  return;
                }
                if ((user.label && user.label.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) != -1)) {
                  postKey = user.treeId;
                  return;
                }
                if(!postKey){
                    (user.children||[]).forEach((p:any) =>{
                    if ((p.label && p.label.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) != -1)) {
                      postKey = p.treeId;
                      return;
                    }
                  })
                }
              })
            }
          });
          if(postKey){
            const node1: any = document.querySelector('.post-tree .el-tree-node[data-key="'+postKey+'"]');
            if(node1){
              node1.scrollIntoView({ block: 'center' });
            }
          }
				});
      }

			const handleSearchReset = () => {
				searchFormRef.value.resetFields();
        state.searchForm.keyword = '';
			}

      const processDepartmentData = computed(() => {
        let treeList = assessmentDepartmentList(state.departments);
        treeList.push({
          id: '-99',
          treeId: '-99',
          label: '无部门人员',
          type: 1,
          children: state.users.filter((user: any)=>{return !user.bmdm;})
        });
        return treeList;
      })

      const assessmentDepartmentList = (list: any[])=> {
        let treeList = [] as UserTreeNode[];
        (list||[]).forEach((department: any)=>{
          const users = state.users.map((user: any)=>{
            return {...user};
          }).filter((user: any)=>{
            return user.bmdm === department.id;
          });
          treeList.push({
            id: department.id,
            treeId: department.id,
            label: department.dprtname,
            type: 1,
            children: assessmentDepartmentList(department.children).concat(users)
          });
        });
        return treeList;
      }

      const processPositionData = computed(() => {
        let treeList = [] as UserTreeNode[];
        (state.positions||[]).forEach((position: any)=>{
            const users = state.users.map((user: any)=>{
              return {...user};
            }).filter((user: any)=>{
              user.treeId = position.id + '__' + user.id;
              return (user.authListVOList || []).some((p: any)=>{ return p.gwid === position.id});
            });
            position.children = users;
          
          treeList.push({
              id: position.id,
              treeId: position.id,
              label: position.mc,
              type: 1,
              children: position.children
            });
        });
        treeList.push({
          id: '-999',
          treeId: '-999',
          label: '不在岗人员',
          type: 1,
          children: state.users.filter((user: any)=>{
            return !user.authListVOList || user.authListVOList.length === 0;
          })
        });
        return treeList;
      })

      const handleCheckChangeByDepartment = (data: any) => {
        const targetNode = departmentTreeRef.value.getNode(data);
        const checked = targetNode.checked;
        const allChildren = getAllChildren(targetNode);
        const uniqueKeys = getDistinctUserKeys(allChildren);
        // 单选时取消其他选中
        if (!state.multi && checked && data.type === 2) { 
          departmentTreeRef.value.setCheckedKeys([], false);
          positionTreeRef.value.setCheckedKeys([], false);
          state.currentSelected = [];
        }
        if (checked) {
          state.currentSelected = mergeAndDistinct(state.currentSelected, uniqueKeys);
          departmentTreeRef.value.setCheckedKeys(state.currentSelected, false);
          positionTreeRef.value.setCheckedKeys(getPositionKeys(departmentTreeRef.value.getCheckedNodes(false)));
        } else {
          state.currentSelected = reduceAndDistinct(state.currentSelected, uniqueKeys);
          departmentTreeRef.value.setCheckedKeys(state.currentSelected, false);
          positionTreeRef.value.setCheckedKeys(getPositionKeys(departmentTreeRef.value.getCheckedNodes(false)));
        }
      }

      const handleCheckChangeByPosition = (data: any) => {
        const targetNode = positionTreeRef.value.getNode(data);
        const checked = targetNode.checked;
        const allChildren = getAllChildren(targetNode);
        const uniqueKeys = getDistinctUserKeys(allChildren);
        // 单选时取消其他选中
        if (!state.multi && checked && data.type === 2) { 
          departmentTreeRef.value.setCheckedKeys([], false);
          positionTreeRef.value.setCheckedKeys([], false);
          state.currentSelected = [];
        }
        if (checked) {
          state.currentSelected = mergeAndDistinct(state.currentSelected, uniqueKeys);
          departmentTreeRef.value.setCheckedKeys(state.currentSelected, false);
          positionTreeRef.value.setCheckedKeys(getPositionKeys(departmentTreeRef.value.getCheckedNodes(false)));
        } else {
          state.currentSelected = reduceAndDistinct(state.currentSelected, uniqueKeys);
          departmentTreeRef.value.setCheckedKeys(state.currentSelected, false);
          positionTreeRef.value.setCheckedKeys(getPositionKeys(departmentTreeRef.value.getCheckedNodes(false)));
        }
      }

      /**
       * 过滤出用户节点并去重
       */
      const getDistinctUserNodes = (nodes) => {
        const filterNodes = nodes.filter((node) => { return node.type === 2})
        const uniqueNodes = filterNodes.filter((node, index) => filterNodes.findIndex((n) => { return n.id === node.id}) === index);
        return uniqueNodes;
      }

      /**
       * 过滤出用户key并去重
       */
      const getDistinctUserKeys = (nodes) => {
        const uniqueNodes = getDistinctUserNodes(nodes);
        const uniqueKeys = uniqueNodes.map((node) => { return node.id});
        return uniqueKeys;
      }

      /**
       * 获取tree某个节点下的所有子节点
       */
      const getAllChildren = (node, allChildren = [node.data]) => {
        if (node.childNodes && node.childNodes.length) {
          node.childNodes.forEach(child => {
            allChildren.push(child.data);
            getAllChildren(child, allChildren);
          });
        }
        return allChildren;
      }

      /**
       * 合并&去重数组
       */
      const mergeAndDistinct = (arr1, arr2) => {
        let merged = arr1.concat(arr2);
        let distinct = Array.from(new Set(merged));
        return distinct;
      }

      /**
       * 缩减&去重数组
       */
      const reduceAndDistinct = (arr1, arr2) => {
        let merged = arr1.filter((obj1) => {return !arr2.some((obj2) => {return obj1 === obj2})});
        let distinct = Array.from(new Set(merged));
        return distinct;
      }

      /**
       * 获取岗位key
       */
      const getPositionKeys = (nodes) => {
        const keys = [];
        nodes.forEach(data => {
            if (data.authListVOList && data.authListVOList.length > 0) {
              data.authListVOList.forEach((position:any) => {
                keys.push(position.gwid +'__' + data.id);
              });
            } else {
              keys.push(data.id);
            }
        });
        return keys;
      }

      const checkedPerson = computed(() => {
        return state.currentSelected.map((obj: any) => {
          return state.allUsers.find((user: any) => {return user.id === obj || user.daid === obj}) || {} as any;
        });
      })

      const handleCloseTag = (tag: any) => {
        if(tag.id){
            departmentTreeRef.value.setChecked(tag.id, false, false);
            if (tag.authListVOList && tag.authListVOList.length > 0) {
              tag.authListVOList.forEach((position:any) => {
                positionTreeRef.value.setChecked(position.gwid +'__' + tag.id, false, false);
              });
            } else {
              positionTreeRef.value.setChecked(tag.id, false, false);
            }
          state.currentSelected = state.currentSelected.filter((obj: any) => {return obj !== tag.id});
        }else{
          state.currentSelected = state.currentSelected.filter(id => 
            state.allUsers.some(user => user.id === id)
          );
        }
      }

      const defaultCheckedKeys4Department = computed(() => {
        let checkedKeys = [] as string[];
        state.users.forEach((user: any) => {
          if ((state.defaultSelected).includes(user.yhid) || (state.defaultSelected).includes(user.daid)) {
            checkedKeys.push(user.id);
          }
        });
        return checkedKeys;
      })

      const defaultCheckedKeys4Position = computed(() => {
        let checkedKeys = [] as string[];
        state.users.forEach((user: any) => {
          if ((state.defaultSelected).includes(user.yhid) || (state.defaultSelected).includes(user.daid)) {
            if (user.authListVOList && user.authListVOList.length > 0) {
              user.authListVOList.forEach((position:any) => {
                checkedKeys.push(position.gwid  + '__' + user.id);
              });
            } else {
              checkedKeys.push(user.id);
            }
          }
        });
        return checkedKeys;
      })

      const setCurrentUsers = () => {
        state.users = state.allUsers.filter((user: any) => {
          if (state.searchForm.keyword) {
            return (user.zh && user.zh.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) > -1) ||
                  (user.xm && user.xm.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) > -1) ||
                  (user.abbr && user.abbr.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) > -1) ||
                  (user.pinyin && user.pinyin.toUpperCase().indexOf(state.searchForm.keyword.toUpperCase()) > -1);
          }
          return user;
        });
      }

      // 多选时，将传入参数中默认选中值，由rydaid重置为为userid
      const handleSelectedParam = () => {
        if (state.type === 2 && state.defaultSelected.length > 0) {
          const yhidList = [] as string[];
          console.info(state.defaultSelected)
          state.defaultSelected.forEach((id: any) => {
            const user = state.allUsers.find((u: any) => { return u.daid === id || u.yhid === id}) as any;
            if (user) {
              yhidList.push(user.yhid);
            }
          })
          state.defaultSelected = [...yhidList];
          state.currentSelected = [...yhidList];
        }
      }

			return {
				...toRefs(state),
				handleSave,
				editDialogRef,
				handleOpen,
				searchFormRef,
				handleSearch,
				handleSearchReset,
        processDepartmentData,
        processPositionData,
        departmentTreeRef,
        positionTreeRef,
        checkedPerson,
        handleCloseTag,
        defaultCheckedKeys4Department,
        defaultCheckedKeys4Position,
        markTextColor,
        handleCheckChangeByDepartment,
        handleCheckChangeByPosition,
			}
		},
	})
</script>
<style scoped lang="scss">
	.custom-tree-label {
		display: flex;
		align-items: center;
		justify-content: space-between;
		font-size: 14px;
		font-weight: bold;
		padding: 0 8px 8px 10px;
	}
</style>